package enum

import (
	"fmt"
	"strings"

	"github.com/micro-plat/lib4go/errs"
)

//请求类型
const (
	Single = iota + 1
	Multi
	Dynamic
)

//加密类型枚举值
const (
	MD5Str    = "md5"
	SHA1Str   = "sha1"
	SHA256Str = "sha256"
	SHA512Str = "sha512"
	HMACStr   = "hmac"
	RSAStr    = "rsa"
	AESStr    = "aes"
	DESStr    = "des"
	CertStr   = "cert"
)

//签名原串排序方式
const (
	All    = "all"
	Data   = "data"
	Static = "static"
)

//签名原串key拼接位置
const (
	Head     = "head"
	Tail     = "tail"
	HeadTail = "headtail"
)

//公有字段默认名
const (
	EUIDName       = "euid"
	SignName       = "sign"
	TimestampName  = "timestamp"
	DynamicKeyName = "secret_id"
)

//加密类型枚举值
const (
	None   = 0
	MD5    = 1
	SHA1   = 2
	SHA256 = 4
	SHA512 = 8
	HMAC   = 16
	RSA    = 32
	AES    = 64
	DES    = 128
	Cert   = 256
)

var signTypes = map[string]string{
	MD5Str:    MD5Str,
	SHA1Str:   SHA1Str,
	SHA256Str: SHA256Str,
	SHA512Str: SHA512Str,
	HMACStr:   HMACStr,
	RSAStr:    RSAStr,
}

//CheckSignType 检查签名类型是否支持
func CheckSignType(sType string, authType int) error {
	if _, ok := signTypes[strings.ToLower(sType)]; !ok {
		return errs.NewError(ERR_PARAMS, fmt.Errorf("%s类型不支持签名", sType))
	}

	//如果是动态/混合方式签名  签名方式不能是rsa等非对称加密
	if (authType == Dynamic || authType == Multi) && sType == RSAStr {
		return errs.NewError(ERR_PARAMS, fmt.Errorf("Dynamic/Multi的签名类型不能是rsa的非对称签名[%s]", sType))
	}
	return nil
}

var encryptTypes = map[string]string{
	AESStr: AESStr,
	DESStr: DESStr,
	RSAStr: RSAStr,
}

//CheckEncryptType 检查加密类型是否支持
func CheckEncryptType(eType string, authType int) error {
	if _, ok := encryptTypes[strings.ToLower(eType)]; !ok {
		return errs.NewError(ERR_PARAMS, fmt.Errorf("%s类型不支持加密", eType))
	}

	//如果是动态加密  签名方式不能是rsa等非对称加密
	if authType == Dynamic && eType == RSAStr {
		return errs.NewError(ERR_PARAMS, fmt.Errorf("Dynamic的加密类型不能是rsa的非对称加密[%s]", eType))
	}
	return nil
}

//typeMap 类型映射map
var typeMap = map[string]map[string]interface{}{
	"md5": {
		"param_name": "md5_secret",
		"value":      MD5,
	},
	"sha1": {
		"param_name": "sha1_secret",
		"value":      SHA1,
	},
	"sha256": {
		"param_name": "sha256_secret",
		"value":      SHA256,
	},
	"sha512": {
		"param_name": "sha512_secret",
		"value":      SHA512,
	},
	"hmac": {
		"param_name": "hmac_secret",
		"value":      HMAC,
	},
	"rsa": {
		"param_name": "rsa_public_secret",
		"value":      RSA,
	},
	"cert": {
		"param_name": "mer_cert",
		"value":      Cert,
	},
	"aes": {
		"param_name": "aes_secret",
		"value":      AES,
	},
	"des": {
		"param_name": "des_secret",
		"value":      DES,
	},
}

// GetNameByValue 按枚举值获取类型对应参数名
func GetNameByValue(enType int) string {
	for _, v := range typeMap {
		if enType == v["value"].(int) {
			return v["param_name"].(string)
		}
	}
	return ""
}

// GetNameByType 按类型获取类型对应参数名
func GetNameByType(enType string) string {
	lType := strings.ToLower(enType)
	v, ok := typeMap[lType]
	if !ok {
		return ""
	}
	return v["param_name"].(string)
}

// GetValueByName 按名称获取枚举值
func GetValueByName(enType string) int {
	lType := strings.ToLower(enType)
	v, ok := typeMap[lType]
	if !ok {
		return 0
	}
	return v["value"].(int)
}

//CheckType 检查类型是否支持
func CheckType(enTypes ...string) error {

	if len(enTypes) <= 0 {
		return errs.NewError(ERR_MissingParam, fmt.Errorf("缺少类型"))
	}
	for i := range enTypes {
		enType := enTypes[i]
		if _, ok := typeMap[strings.ToLower(enType)]; !ok {
			return errs.NewError(ERR_PARAMS, fmt.Errorf("%s类型不支持", enType))
		}
	}

	return nil
}

//GetTypes 获取类型
func GetTypes() []string {
	keys := make([]string, 0, len(typeMap))
	for k := range typeMap {
		keys = append(keys, k)
	}
	return keys

}

const (
	ERR_PARAMS   = 901
	ERR_NotExits = 902 //

	ERR_NotGenerate        = 903 //该类型密钥未生成
	ERR_NotSupport         = 904
	ERR_MissingParam       = 905
	ERR_NotRemoteConfig    = 906
	ERR_ExistsSecret       = 907
	ERR_NotExitsSecretType = 908 //

	ERR_DataFormat = 999
)
